﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Runtime.Serialization.Formatters.Binary;

using dict = System.Collections.DictionaryEntry;

namespace nr.GLV.Windows.Controls
{
    public delegate void DataChangedEventHandler(object sender, EventArgs e);

    public class ArchiveUserControl : System.Windows.Forms.UserControl
    {
        private System.Windows.Forms.Label lblTitle;
        protected System.Windows.Forms.SplitContainer dataContainer;
        private MenuStrip mnuFilter;
        private System.Windows.Forms.ToolStripMenuItem miFilterMenu;
        private System.Windows.Forms.ToolStripMenuItem miFilterView;
        private System.Windows.Forms.ToolStripMenuItem miFiltersAdd;
        private System.Windows.Forms.ToolStripMenuItem miFiltersAddAnd;
        private System.Windows.Forms.ToolStripMenuItem miFiltersAddOr;
        private System.Windows.Forms.ToolStripMenuItem miFiltersDelete;
        private System.Windows.Forms.TreeView tvFilters;
        private ToolStripMenuItem miFilterToggle;
        private ToolStripSeparator miFilterSep1;
        protected System.Windows.Forms.SplitContainer container;

        public event RecordCountChangedEventHandler RecordNumberChanged;
        public event FilterApplyEventHandler FilterApply;
        public event FilterResetEventHandler FilterReset;
        public event DataChangedEventHandler DataChanged;
        public event DeleteCommandEnabledChangedEventHandler DeleteCommandEnabledChanged;

        private nr.GLV.Data.nrDataSet data;
        public nr.GLV.Data.nrDataSet Data { get { return data; } set { data = value; OnDataChanged(EventArgs.Empty); } }

        private FilterOperator[] stdop = 
            {
                new FilterOperator(){Text = "uguale a", Value="="},
                new FilterOperator(){Text = "simile a", Value = "LIKE"},
                new FilterOperator(){Text = "diverso da",Value="<>"},
                new FilterOperator(){Text = "minore di", Value="<"},
                new FilterOperator(){Text = "maggiore di", Value=">"}
            };

        public List<FilterOperator> Operators;
        public List<FilterField> FilterFields { get; private set; }

        public string Title { get { return lblTitle.Text; } set { lblTitle.Text = value; } }

        protected virtual void OnRecordCountChanged(RecordCountChangedEventArgs e)
        {
            if (RecordNumberChanged != null)
                RecordNumberChanged.Invoke(this, e);
        }

        public bool CanBeFiltered { get { return miFilterMenu.Visible; } set { miFilterMenu.Visible = value; } }

        public bool IsFilterVisibile { get { return !dataContainer.Panel1Collapsed; } set { dataContainer.Panel1Collapsed = !value; } }

        public void ToggleFilterArea()
        {
            dataContainer.Panel1Collapsed = !dataContainer.Panel1Collapsed;
        }

        public ArchiveUserControl()
            : base()
        {
            InitializeComponent();
            CanBeFiltered = false;
            FilterFields = new List<FilterField>();
            Operators = new List<FilterOperator>();
            Operators.AddRange(stdop);
        }

        private void InitializeComponent()
        {
            System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Filtri");
            this.container = new System.Windows.Forms.SplitContainer();
            this.lblTitle = new System.Windows.Forms.Label();
            this.dataContainer = new System.Windows.Forms.SplitContainer();
            this.tvFilters = new System.Windows.Forms.TreeView();
            this.mnuFilter = new System.Windows.Forms.MenuStrip();
            this.miFilterMenu = new System.Windows.Forms.ToolStripMenuItem();
            this.miFiltersAdd = new System.Windows.Forms.ToolStripMenuItem();
            this.miFiltersAddAnd = new System.Windows.Forms.ToolStripMenuItem();
            this.miFiltersAddOr = new System.Windows.Forms.ToolStripMenuItem();
            this.miFiltersDelete = new System.Windows.Forms.ToolStripMenuItem();
            this.miFilterSep1 = new System.Windows.Forms.ToolStripSeparator();
            this.miFilterToggle = new System.Windows.Forms.ToolStripMenuItem();
            this.miFilterView = new System.Windows.Forms.ToolStripMenuItem();
            this.container.Panel1.SuspendLayout();
            this.container.Panel2.SuspendLayout();
            this.container.SuspendLayout();
            this.dataContainer.Panel1.SuspendLayout();
            this.dataContainer.Panel2.SuspendLayout();
            this.dataContainer.SuspendLayout();
            this.mnuFilter.SuspendLayout();
            this.SuspendLayout();
            // 
            // container
            // 
            this.container.Dock = System.Windows.Forms.DockStyle.Fill;
            this.container.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
            this.container.IsSplitterFixed = true;
            this.container.Location = new System.Drawing.Point(0, 0);
            this.container.Name = "container";
            this.container.Orientation = System.Windows.Forms.Orientation.Horizontal;
            // 
            // container.Panel1
            // 
            this.container.Panel1.Controls.Add(this.lblTitle);
            // 
            // container.Panel2
            // 
            this.container.Panel2.Controls.Add(this.dataContainer);
            this.container.Size = new System.Drawing.Size(308, 261);
            this.container.SplitterDistance = 25;
            this.container.TabIndex = 2;
            // 
            // lblTitle
            // 
            this.lblTitle.BackColor = System.Drawing.SystemColors.ActiveCaption;
            this.lblTitle.Dock = System.Windows.Forms.DockStyle.Fill;
            this.lblTitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.lblTitle.ForeColor = System.Drawing.SystemColors.HotTrack;
            this.lblTitle.Location = new System.Drawing.Point(0, 0);
            this.lblTitle.Name = "lblTitle";
            this.lblTitle.Size = new System.Drawing.Size(308, 25);
            this.lblTitle.TabIndex = 0;
            this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // dataContainer
            // 
            this.dataContainer.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
            this.dataContainer.Location = new System.Drawing.Point(0, 0);
            this.dataContainer.Name = "dataContainer";
            // 
            // dataContainer.Panel1
            // 
            this.dataContainer.Panel1.Controls.Add(this.tvFilters);
            this.dataContainer.Panel1MinSize = 170;
            // 
            // dataContainer.Panel2
            // 
            this.dataContainer.Panel2.Controls.Add(this.mnuFilter);
            this.dataContainer.Size = new System.Drawing.Size(308, 232);
            this.dataContainer.SplitterDistance = 170;
            this.dataContainer.TabIndex = 0;
            // 
            // tvFilters
            // 
            this.tvFilters.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tvFilters.HideSelection = false;
            this.tvFilters.Location = new System.Drawing.Point(0, 0);
            this.tvFilters.Name = "tvFilters";
            treeNode2.Name = "root";
            treeNode2.Text = "Filtri";
            this.tvFilters.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode2});
            this.tvFilters.Size = new System.Drawing.Size(170, 232);
            this.tvFilters.TabIndex = 0;
            this.tvFilters.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.tvFilters_AfterSelect);
            // 
            // mnuFilter
            // 
            this.mnuFilter.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.miFilterMenu});
            this.mnuFilter.Location = new System.Drawing.Point(0, 0);
            this.mnuFilter.Name = "mnuFilter";
            this.mnuFilter.Size = new System.Drawing.Size(134, 24);
            this.mnuFilter.TabIndex = 0;
            this.mnuFilter.Text = "mnuFilters";
            this.mnuFilter.Visible = false;
            // 
            // miFilterMenu
            // 
            this.miFilterMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.miFiltersAdd,
            this.miFiltersDelete,
            this.miFilterSep1,
            this.miFilterToggle,
            this.miFilterView});
            this.miFilterMenu.MergeAction = System.Windows.Forms.MergeAction.Insert;
            this.miFilterMenu.MergeIndex = 3;
            this.miFilterMenu.Name = "miFilterMenu";
            this.miFilterMenu.Size = new System.Drawing.Size(46, 20);
            this.miFilterMenu.Text = "&Filtro";
            // 
            // miFiltersAdd
            // 
            this.miFiltersAdd.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.miFiltersAddAnd,
            this.miFiltersAddOr});
            this.miFiltersAdd.Name = "miFiltersAdd";
            this.miFiltersAdd.Size = new System.Drawing.Size(205, 22);
            this.miFiltersAdd.Text = "&Aggiungi Filtro...";
            // 
            // miFiltersAddAnd
            // 
            this.miFiltersAddAnd.Name = "miFiltersAddAnd";
            this.miFiltersAddAnd.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.A)));
            this.miFiltersAddAnd.Size = new System.Drawing.Size(150, 22);
            this.miFiltersAddAnd.Text = "&AND...";
            this.miFiltersAddAnd.Click += new System.EventHandler(this.miFiltersAddAnd_Click);
            // 
            // miFiltersAddOr
            // 
            this.miFiltersAddOr.Name = "miFiltersAddOr";
            this.miFiltersAddOr.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
            this.miFiltersAddOr.Size = new System.Drawing.Size(150, 22);
            this.miFiltersAddOr.Text = "&OR...";
            this.miFiltersAddOr.Click += new System.EventHandler(this.miFiltersAddOr_Click);
            // 
            // miFiltersDelete
            // 
            this.miFiltersDelete.Enabled = false;
            this.miFiltersDelete.Name = "miFiltersDelete";
            this.miFiltersDelete.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.R)));
            this.miFiltersDelete.ShowShortcutKeys = false;
            this.miFiltersDelete.Size = new System.Drawing.Size(205, 22);
            this.miFiltersDelete.Text = "&Cancella Filtro Selezionato";
            this.miFiltersDelete.Click += new System.EventHandler(this.miFiltersDelete_Click);
            this.miFiltersDelete.EnabledChanged += new System.EventHandler(this.miFiltersDelete_EnabledChanged);
            // 
            // miFilterSep1
            // 
            this.miFilterSep1.Name = "miFilterSep1";
            this.miFilterSep1.Size = new System.Drawing.Size(202, 6);
            // 
            // miFilterToggle
            // 
            this.miFilterToggle.Name = "miFilterToggle";
            this.miFilterToggle.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.F)));
            this.miFilterToggle.Size = new System.Drawing.Size(205, 22);
            this.miFilterToggle.Text = "&Filtra dati";
            this.miFilterToggle.Click += new System.EventHandler(this.miFilterToggle_Click);
            // 
            // miFilterView
            // 
            this.miFilterView.Name = "miFilterView";
            this.miFilterView.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.T)));
            this.miFilterView.Size = new System.Drawing.Size(205, 22);
            this.miFilterView.Text = "Visualizza &Filtri";
            this.miFilterView.Click += new System.EventHandler(this.miFilterView_Click);
            // 
            // ArchiveUserControl
            // 
            this.Controls.Add(this.container);
            this.Name = "ArchiveUserControl";
            this.Size = new System.Drawing.Size(308, 261);
            this.Load += new System.EventHandler(this.ArchiveUserControl_Load);
            this.container.Panel1.ResumeLayout(false);
            this.container.Panel2.ResumeLayout(false);
            this.container.ResumeLayout(false);
            this.dataContainer.Panel1.ResumeLayout(false);
            this.dataContainer.Panel2.ResumeLayout(false);
            this.dataContainer.Panel2.PerformLayout();
            this.dataContainer.ResumeLayout(false);
            this.mnuFilter.ResumeLayout(false);
            this.mnuFilter.PerformLayout();
            this.ResumeLayout(false);

        }

        private void ArchiveUserControl_Load(object sender, EventArgs e)
        {
            if ((ParentForm != null) && (ParentForm.MainMenuStrip != null))
                System.Windows.Forms.ToolStripManager.Merge(mnuFilter, ParentForm.MainMenuStrip);

            if (IsFilterVisibile) ToggleFilterArea();
        }

        private void miFilterView_Click(object sender, EventArgs e)
        {
            ToggleFilterArea();
            miFilterView.Checked = !dataContainer.Panel1Collapsed;
        }

        private void tvFilters_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
        {
            miFiltersDelete.Enabled = (e.Node != tvFilters.Nodes[0]);
        }

        protected void AddAndFilter(FilterInfo info)
        {
            TreeNode selected = tvFilters.SelectedNode;
            if (selected == null) selected = tvFilters.Nodes[0];
            info.Text = info.ToString();
            selected.Nodes.Add(info);
            tvFilters.ExpandAll();
            tvFilters.SelectedNode = info;
        }

        protected void AddOrFilter(FilterInfo info)
        {
            TreeNode selected = tvFilters.SelectedNode;
            if ((selected == null) || (selected.Parent == null))
                selected = tvFilters.Nodes[0];
            else
                selected = selected.Parent;
            selected.Nodes.Add(info);
            tvFilters.ExpandAll();
            tvFilters.SelectedNode = info;
        }

        private string GetFilters(TreeNode startNode)
        {
            StringBuilder result = new StringBuilder();

            foreach (TreeNode node in startNode.Nodes)
            {
                FilterInfo f = (FilterInfo)node;
                result.Append(string.Format(f.Field.FilterText, f.Operator.Value, f.ValueToCompare));
                if (node.Nodes.Count > 0)
                    result.AppendFormat(" AND ({0}) ", GetFilters(node));

                result.Append(" OR ");
            }
            if (result.Length > 0)
                result.Remove(result.Length - 4, 4);
            return result.ToString();
        }

        protected string GetFilters()
        {
            return GetFilters(tvFilters.Nodes[0]);
        }

        private void miFilterToggle_Click(object sender, EventArgs e)
        {
            miFilterToggle.Checked = !miFilterToggle.Checked;

            if (miFilterToggle.Checked)
            {
                if (!IsFilterVisibile) ToggleFilterArea();
                OnFilterApply(EventArgs.Empty);
            }
            else
                OnFilterReset(EventArgs.Empty);
        }

        protected virtual void OnFilterReset(EventArgs e)
        {
            if (FilterReset != null) FilterReset(this, e);
        }

        protected virtual void OnFilterApply(EventArgs e)
        {
            if (FilterApply != null) FilterApply(this, e);
        }

        private FilterInputForm GetFilterInputForm()
        {
            FilterInputForm frm = new FilterInputForm();
            frm.Fields = FilterFields;
            frm.Operators = Operators;
            return frm;
        }

        protected void PerformAddAndFilter()
        {
            if (!IsFilterVisibile) ToggleFilterArea();
            OnFilterReset(EventArgs.Empty);
            FilterInputForm frm = GetFilterInputForm();
            if (frm.ShowDialog(this) == DialogResult.OK)
            {
                FilterInfo f = frm.FilterInfo;
                AddAndFilter(f);
            }
        }

        private void miFiltersAddAnd_Click(object sender, EventArgs e)
        {
            PerformAddAndFilter();
        }

        protected void PerformAddOrFilter()
        {
            if (!IsFilterVisibile) ToggleFilterArea();
            OnFilterReset(EventArgs.Empty);
            FilterInputForm frm = GetFilterInputForm();
            if (frm.ShowDialog(this) == DialogResult.OK)
            {
                FilterInfo f = frm.FilterInfo;
                AddOrFilter(f);
            }
        }

        private void miFiltersAddOr_Click(object sender, EventArgs e)
        {
            PerformAddOrFilter();
        }

        protected virtual void OnDataChanged(EventArgs e)
        {
            if (DataChanged != null) DataChanged(this, e);
        }

        private void miFiltersDelete_Click(object sender, EventArgs e)
        {
            OnFilterReset(EventArgs.Empty);
            tvFilters.SelectedNode.Remove();
            tvFilters.SelectedNode = tvFilters.Nodes[0];
        }

        private void miFiltersDelete_EnabledChanged(object sender, EventArgs e)
        {
            OnDeleteCommandEnabledChanged(new DeleteCommandEnabledChangedEventArgs(miFiltersDelete.Enabled));
        }

        protected virtual void OnDeleteCommandEnabledChanged(DeleteCommandEnabledChangedEventArgs e)
        {
            if (DeleteCommandEnabledChanged != null)
                DeleteCommandEnabledChanged(this, e);
        }
    }
}
